#ifndef __BLE_H__
#define __BLE_H__
#include "osal.h"

/* 蓝牙协议对应命令CMD */
#define BLE_CMD_ACK 0X00                    // ACK
#define BLE_CMD_AUTHENTICATION 0x01         //鉴权
#define BLE_CMD_LOCK_CONTROL 0x02           //锁控制
#define BLE_CMD_KEY_MGMT 0x03               //密钥管理
#define BLE_CMD_OPEN_LOCK_RECORDS 0x04      //获取开锁记录
#define BLE_CMD_NOTIFICATION 0x05           //锁状态消息上报
#define BLE_CMD_UPDATE_PARAM 0x06           //修改门锁参数
#define BLE_CMD_ALARM_REPORT 0x07           //锁报警消息上报
#define BLE_CMD_PWD_REPORT 0x08             // AES密钥上报
#define BLE_CMD_USER_TYPE_SET 0x09          //用户类型设置
#define BLE_CMD_USER_TYPE_GET 0x0A          //用户类型查询
#define BLE_CMD_SCHEDULE_WEEK_SET 0x0B      //周计划设置
#define BLE_CMD_SCHEDULE_WEEK_GET 0x0C      //周计划查询
#define BLE_CMD_SCHEDULE_WEEK_CLEAR 0x0D    //周计划删除
#define BLE_CMD_SCHEDULE_YEARDAY_SET 0x0E   //年月日计划设置
#define BLE_CMD_SCHEDULE_YEARDAY_GET 0x0F   //年月日计划查询
#define BLE_CMD_SCHEDULE_YEARDAY_CLEAR 0x10 //年月日计划上传
#define BLE_CMD_SYNC_KEY_STATE 0x11         //同步门锁密钥状态
#define BLE_CMD_GET_LOCK_PARAM 0x12         //查询门锁基本信息
#define BLE_CMD_APP_BIND_REQUEST 0x13       // APP绑定请求
#define BLE_CMD_ALARM_RECORDS 0x14          //锁报警记录查询
#define BLE_CMD_LOCK_PARAM 0x17             //锁参数主动查询
#define BLE_CMD_ANY_RECORDS 0x18            //锁记录查询(开门记录、报警记录、秘钥操作记录、混合记录)
#define BLE_CMD_LOCK_SN 0x15                //锁序列号查询
#define BLE_CMD_OPEN_LOCK_TIMES 0x16        //锁开锁次数查询
#define BLE_CMD_LOCK_PARAM 0x17             //锁参数主动查询
#define BLE_CMD_ANY_RECORDS 0x18            //锁记录查询(开门记录、报警记录、秘钥操作记录、混合记录)
#define BLE_CMD_ANY_RECORDS_ALFRED 0x19     // Alfred锁记录查询(开门记录、报警记录、秘钥操作记录、混合记录)
#define BLE_CMD_EVENT_REPORT_ALFRED 0x1A    //锁事件上报
#define BLE_CMD_PAIR 0x1B                   // 配对帧
#define BLE_CMD_KEY_ATTR_OPTION 0X1C        //密钥属性设置
#define BLE_CMD_KEY_ATTR_READ 0X1D          //密钥属性读
#define BLE_CMD_ADD_KEY 0X1E                //添加密钥返回密钥编号
#define BLE_DOOR_MAGNETIC_CAL 0X1F          //门磁校准
#define BLE_SHAKE_SENSOR_SET 0X20           //敲门开锁灵敏度设置
#define BLE_SET_AUTO_LOCKED_TIME 0X21       //设置自动上锁时间
#define BLE_SHAKE_OPEN_DOOR 0X22            //设置敲门开锁
#define BLE_SET_GMT_TIME 0X23               //通过格林威治时间设置锁时间
#define BLE_READ_MANY_RECORD 0X24           //读任何记录
#define BLE_FORCE_CONTROL 0X25              //胁迫密码功能开关
#define BLE_CONTROL_WIFI_OPEN_CLOSE 0X26    // WIFI开关控制
#define BLE_READ_SOFTWARE_VER 0X27          //读取软件版本
#define BLE_SET_TIME_ZONE_AND_TIME 0X28     //设置时区以及时间
#define BLE_CMD_HEART 0xAA                  //心跳
/********************配网部分*********************/
#define CMD_APP_SEND_SSID 0X90          // APP下发SSID命令
#define CMD_APP_SEND_PWD 0X91           // APP下发密码命令
#define CMD_REPORT_OFFLINE_PASSWD 0X92  //上报离线密码因子
#define CMD_UPLOAD_NET_STATUS 0X93      //上报配网状态
#define CMD_VERIFY_OFFLINE_PASSWD 0X94  // APP校验离线密码结果
#define CMD_UPLOAD_VERIFY_NUM 0X95      //上报验证剩余次数
#define CMD_STOP_PAIR_NET 0X96          //停止配网
#define CMD_MQTT_CONNECT_SUCCEED 0X97   // MQTT连接成功
#define CMD_APP_SEND_CMD_WIFI_SCAN 0X98 // APP下发命令启动WIFI scan
/********************锁帖部分*********************/
#define BLE_CMD_BIND_SUB_DEVICE 0X31 // 绑定子设备
#define BLE_CMD_DEL_SUB_DEVICE 0X32  // 删除子设备
#define BLE_BIND_DEVICE_RESULT 0X33  // 上报绑定子设备结果
#define BLE_CMD_PARAM_INQUIRE 0X34   // 参数查询
#define BLE_CMD_ADD_FINGER_TIME 0X35 // 上报添加指纹按下次数
/********************OTA部分*********************/
#define BLE_CMD_OTA_REQUEST 0XA1 // ota升级请求
#define BLE_CMD_OTA_RESULT 0XA2  // ota升级结果
/********************降成本新增部分*********************/
#define BLE_CMD_ADD_KEY_STATE 0X35      // 密钥添加引导
#define BLE_CMD_ADD_KEY_POLICY 0X36     // 密钥策略添加
#define BLE_CMD_DEL_ALL_KEY_REQ 0X37    // 密钥批量删除请求
#define BLE_CMD_QUERY_KEYS 0x38         // 查询密钥
#define BLE_CMD_ADD_KEY_AND_POLICY 0X39 //添加秘钥以及属性 新协议废弃0X36命令
#define BLE_BIND_REQUEST 0XF0           // 绑定请求
#define BLE_BIND_ATTEST_REQUEST 0XF1    // 绑定认证请求
#define BLE_BIND_ATTEST_RESPOND 0XF2    // 绑定认证响应
#define BLE_SESSION_KEY_RESPOND 0XF3    // 会话密钥响应

#define BLE_ALRAM_TYPE_LOW_POWER ((uint32_t)1 << 0)
#define BLE_ALRAM_TYPE_SYS_LOCK ((uint32_t)1 << 1)
#define BLE_ALRAM_TYPE_FORCE_KEY ((uint32_t)1 << 5)
#define BLE_ALRAM_TYPE_OVER_CURRENT ((uint32_t)1 << 10)
#define BLE_ALRAM_TYPE_MECHANICAL_KEY ((uint32_t)1 << 13)

#define DOORLOCK_CMD_CHECK_MODE_CLAC 0x01   /// 计算发出的check
#define DOORLOCK_CMD_CHECK_MODE_VERIFY 0x02 /// 校验收到的cheak和计算出来的低字节
#define DOORLOCK_FRAME_CONTROL_FLAG_INIT 0x00
#define DOORLOCK_FRAME_CONTROL_FLAG_CRYPTO 0x01

// 0xbd-bf are reserved.
#define DOORLOCK_STATUS_HARDWARE_FAILURE 0XC0
#define DOORLOCK_STATUS_SOFTWARE_FAILURE 0XC1
#define DOORLOCK_STATUS_CALIBRATION_ERROR 0XC2 /// 上传检验check失败的命令

/********************log打印*********************/
#define A4_FMT " %02X%02X%02X%02X"
#define A8_FMT A4_FMT A4_FMT
#define A12_FMT A4_FMT A8_FMT
#define A16_FMT A8_FMT A8_FMT

#define PRINT_A6(a) *(a), *(a + 1), *(a + 2), *(a + 3), *(a + 4), *(a + 5)
#define PRINT_A8(a) PRINT_A6(a), *(a + 6), *(a + 7)
#define PRINT_A12(a) PRINT_A6(a), PRINT_A6(a + 6)
#define PRINT_A16(a) PRINT_A8(a), PRINT_A8(a + 8)

#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x\r\n"

/* 锁收到网络模块的命令后，执行的结果 */
typedef enum
{
    CMD_EXECUTING,                //命令正在执行，还需再次执行才能得到结果
    CMD_EXE_ONCE,                 //命令执行完一次，还需要再次执行 一对多未发完时调用
    CMD_EXE_OK = 0x80,            //命令执行成功 一对一指令调用
    CMD_EXE_ERR = 0x81,           //命令执行失败
    CMD_EXE_OK_END = 0x82,        //命令执行结束（当有多个应答包时，最后一个应答发0x82）
    CMD_EXE_PWD_EXISTED = 0x83,   //密钥已存在
    CMD_EXE_PWD_UNKNOW = 0x84,    //密钥不存在
    CMD_EXE_FULL = 0x85,          //配满
    CMD_EXE_NUM_EXISTED = 0x86,   //编号已存在
    CMD_EXE_NUM_UNKNOW = 0x87,    //编号不存在
    CMD_EXE_NO_FUNCTION = 0x88,   //无此功能
    CMD_EXE_OPEN_LOCK_ERR = 0x8C, //开锁失败，为安全模式
    CMD_EXE_NUM_OVERFLOW = 0x8D,  //编号超出范围
    CMD_EXE_PWD_TOOSIMPLE = 0x8E, //密码过于简单
    CMD_EXE_PWD_INVALID = 0x8F,   //密码无效
    CMD_EXE_DEL_FAILED = 0x90,    //删除失败，为安全模式
    CMD_EXE_NO_TWO_PWD = 0x91,    //没有2种不同类型的密钥
    CMD_EXE_NO_AUTHORITY = 0x94,  //没有权限

    CMD_EXE_ID_ERR = 0X92,      // ID号错误
    CMD_EXE_UNKNOW = 0X93,      //未知命令
    CMD_EXE_VERIFY_LOCK = 0X95, //验证锁定
} RxCmdExecuteRes_enum_t;

/*** 收到的命令位对应宏 ***/
typedef enum
{
    DOORLOCK_FRAME_CON_POS = 0, // 0 加密
    DOORLOCK_FRAME_TSN_POS,     // 1 TSN
    DOORLOCK_FRAME_CHK_POS,     // 2 数据和累加低字节
    DOORLOCK_FRAME_CMD_POS,     // 3 cmd命令
    DOORLOCK_FRAME_STATUS_POS,  // 4 数据域
} BleCmdPos_enum_t;

/*** 正确错误码 ***/
typedef enum
{
    DOORLOCK_STATUS_SUCCESS = 0x00,        // 正确
    DOORLOCK_STATUS_FAILURE,               // 错误
    DOORLOCK_STATUS_NOT_AUTHORIZED = 0x7E, // 数据和累加低字节
    DOORLOCK_STATUS_INVALID_FIELD = 0x85,  // 无效字段
} BleStatus_enum_t;

/* 应用层下发数据的source */
#define BLE_MSG_ACK 0
#define BLE_MSG_CMD 1
#define BLE_WIFI_ACK 2
#define BLE_WIFI_CMD 3
#define MAX_MSG_LEN (248) /// 单个缓存最大长度

#pragma pack(1)
/* 蓝牙邮箱下发消息（应用层->COMP） */
typedef struct
{
    uint8_t source;                 // 0：不需要加密 1：需要加密
    uint8_t cmd;                    // 发过来的命令
    uint8_t ret;                    // 是否发送完毕
    uint8_t len;                    // 数据长度
    uint8_t pData[MAX_MSG_LEN - 4]; // 数据
} BleCallbackMsg_t;

/* 绑定子设备发来的数据 */
typedef struct
{
    uint8_t DeviceType; // 子设备类型
    uint8_t ESN[13];    // 子设备ESN
    uint8_t PWD1[12];   // 子设备PWD1
} SubDevData_stu_t;

/* 发送绑定子设备结果需要签名的内容 32 */
typedef struct
{
    uint8_t ImageID[5]; // 镜像编号
    uint8_t DeviceType; // 子设备类型
    uint8_t SubVer[9];  // 子设备版本号
    uint8_t SubESN[13]; // 子设备ESN
    uint32_t Timestamp; // 时间
} SubDevBindEndData_stu_t;

/* 发送绑定子设备结果内容 65 */
typedef struct
{
    uint8_t BindState;                // 绑定结果 0成功 1失败 0x94超时
    SubDevBindEndData_stu_t BindData; // 发送数据
    uint8_t Signature[32];            // 签名
} SendSubDevBindEnd_stu_t;

/* 蓝牙PUBLISH消息（COMP->应用层）*/
typedef struct
{
    uint8_t type;    // 数据类型
    uint8_t cmd;     // 发过来的命令
    uint8_t len;     // 数据长度
    uint8_t pData[]; // 数据
} BlePublishMsg_t;
#pragma pack()

/*
 * 发送数据包（应用层->COMP）
 * param：该参数是个结构体指针：LockSendBleMsg_t*
 */
#define Ble_SendDataToBle(str, len)                      \
    ({                                                   \
        uint8_t *temp = (uint8_t *)OSAL_Malloc(len + 5); \
        temp[0] = BLE_CTRL_DATA;                         \
        memcpy((char *)&temp[1], str, (len + 4));        \
        OSAL_MboxPost(COMP_BLE, 0, temp, (len + 5));     \
        OSAL_Free(temp);                                 \
    })

/*
 * 设置BLE广播（应用层->COMP）
 * adv_data：广播数据---该参数是个结构体指针：BleAdv_stu_t*
 * time：广播时间（单位：秒）
 *       0xFFFF：永久广播
 *       0x0000：关闭广播
 */
#define Ble_SetAdv(time, adv_data)                                        \
    ({                                                                    \
        uint8_t *temp = (uint8_t *)OSAL_Malloc(sizeof(BleAdv_stu_t) + 3); \
                                                                          \
        temp[0] = BLE_CTRL_SET_ADV;                                       \
        memcpy(&temp[1], &time, 2);                                       \
        if (time == 0)                                                    \
            memset(&temp[3], 0, sizeof(BleAdv_stu_t));                    \
        else                                                              \
            memcpy(&temp[3], adv_data, sizeof(BleAdv_stu_t));             \
        OSAL_MboxPost(COMP_BLE, 0, temp, sizeof(BleAdv_stu_t) + 3);       \
        OSAL_Free(temp);                                                  \
    })

/*
 * 设置BLE参数（应用层->COMP）
 * param：该参数是个结构体指针：BleParam_stu_t*
 */
#define Ble_SetParam(param)                                                 \
    ({                                                                      \
        uint8_t *temp = (uint8_t *)OSAL_Malloc(sizeof(BleParam_stu_t) + 1); \
                                                                            \
        temp[0] = BLE_CTRL_SET_PARAM;                                       \
        memcpy(&temp[1], param, sizeof(BleParam_stu_t));                    \
        OSAL_MboxPost(COMP_BLE, 0, temp, sizeof(BleParam_stu_t) + 1);       \
        OSAL_Free(temp);                                                    \
    })
/*
 * 设置BLE 广播地址（应用层->COMP）
 * param：该参数是个结构体指针：BleParam_stu_t*
 */
#define Ble_Set_MAC(mac)                                \
    ({                                                  \
        uint8_t temp[6 + 1] = {0};                      \
        temp[0] = BLE_CTRL_SET_MAC;                     \
        memcpy(&temp[1], mac, 6);                       \
        OSAL_MboxPost(COMP_BLE, 0, temp, sizeof(temp)); \
    })

/* 获取PWD2 */
#define Ble_GetPwd2(pwd2)                           \
    ({                                              \
        OSAL_NvReadGlobal(COMP_BLE, 0, 0, pwd2, 4); \
    })

/********************降成本新增部分*********************/
/*
 * 设置DOORLOCK服务参数（应用层->COMP）
 * param：DOORLOCK服务参数，12字节
 */
#define Ble_SetDoorLock(str)                            \
    ({                                                  \
        uint8_t *temp = (uint8_t *)OSAL_Malloc(12 + 1); \
                                                        \
        temp[0] = BLE_CTRL_DOOR_LOCK;                   \
        memcpy(&temp[1], str, 12);                      \
        OSAL_MboxPost(COMP_BLE, 0, temp, 12 + 1);       \
        OSAL_Free(temp);                                \
    })

/*
 * 设置BLE模块参数（应用层->COMP）
 * param：BLE模块参数，9字节
 */
#define Ble_SetModuleparam(str)                        \
    ({                                                 \
        uint8_t *temp = (uint8_t *)OSAL_Malloc(9 + 1); \
                                                       \
        temp[0] = BLE_CTRL_MODULE_PARAM;               \
        memcpy(&temp[1], str, 9);                      \
        OSAL_MboxPost(COMP_BLE, 0, temp, 9 + 1);       \
        OSAL_Free(temp);                               \
    })

/*
 * 设置蓝牙频偏校准指令（应用层->COMP）
 * param：蓝牙地址（7字节）+ GATT handle（2字节），9字节
 */
#define Ble_SetOffsetCal(str)                          \
    ({                                                 \
        uint8_t *temp = (uint8_t *)OSAL_Malloc(9 + 1); \
        if (temp)                                      \
        {                                              \
            temp[0] = BLE_CTRL_CALIBRATION;            \
            memcpy(&temp[1], str, 9);                  \
            OSAL_MboxPost(COMP_BLE, 0, temp, 9 + 1);   \
            OSAL_Free(temp);                           \
        }                                              \
    })

/*
 * 下发PWDb给组件（应用层->COMP）
 * str：PWDb，16字节
 */
#define Ble_SendPWDb(str)                               \
    ({                                                  \
        uint8_t *temp = (uint8_t *)OSAL_Malloc(16 + 1); \
                                                        \
        temp[0] = BLE_CTRL_SEND_PWDB;                   \
        memcpy(&temp[1], str, 16);                      \
        OSAL_MboxPost(COMP_BLE, 0, temp, 16 + 1);       \
        OSAL_Free(temp);                                \
    })

/*
 * 操控蓝牙连接（应用层->COMP）
 * flag：0：断开连接 1：主动连接
 */
#define Ble_Setconnect(flag)                        \
    ({                                              \
        uint8_t temp[2] = {BLE_CTRL_CONNECT, flag}; \
        OSAL_MboxPost(COMP_BLE, 0, temp, 2);        \
    })

/* 
 * 设置加密标志（应用层->COMP）
 * flag：0：不加密 1：加密
 */
#define Ble_Encryptionflag(flag)                        \
    ({                                              \
        uint8_t temp[2] = {BlE_CTRL_ENCRYPTION, flag}; \
        OSAL_MboxPost(COMP_BLE, 0, temp, 2);        \
    })

/* 获取gatt和频偏 */
// #define Ble_GetGATT(str)                           \
//     ({                                             \
//         OSAL_NvReadGlobal(COMP_BLE, 0, 0, str, 3); \
//     })
/* 校频获取设备GATT */
void Ble_GetGATT(uint8_t *data);

/*
 * 射频开关指令（应用层->COMP）
 * str[0]：0：关闭射频 1：打开射频
 * str[1]：蓝牙频率低字节 str[2]：蓝牙频率高字节
 */
#define Ble_SetRadioFreqen(str)                        \
    ({                                                 \
        uint8_t *temp = (uint8_t *)OSAL_Malloc(3 + 1); \
                                                       \
        temp[0] = BLE_CTRL_RADIOFREQEN;                \
        memcpy(&temp[1], str, 3);                      \
        OSAL_MboxPost(COMP_BLE, 0, temp, 3 + 1);       \
        OSAL_Free(temp);                               \
    })

#endif /* __BLE_H__ */
